package com.rpi;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.Pin;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.RaspiPin;
import com.rpi.action.GpioListener;

public class HomeAutomationStartup {

	private static Logger log = LoggerFactory.getLogger(HomeAutomationStartup.class);
	private static Map<String, Pin> pinMap = new HashMap<String, Pin>();

	private final GpioController gpioController = GpioFactory.getInstance();
	
	static {
		pinMap.put("GPIO_00", RaspiPin.GPIO_00);
		pinMap.put("GPIO_01", RaspiPin.GPIO_01);
		pinMap.put("GPIO_02", RaspiPin.GPIO_02);
		pinMap.put("GPIO_03", RaspiPin.GPIO_03);
		pinMap.put("GPIO_04", RaspiPin.GPIO_04);
		pinMap.put("GPIO_05", RaspiPin.GPIO_05);
		pinMap.put("GPIO_06", RaspiPin.GPIO_06);
		pinMap.put("GPIO_07", RaspiPin.GPIO_07);
		pinMap.put("GPIO_08", RaspiPin.GPIO_08);
		pinMap.put("GPIO_09", RaspiPin.GPIO_09);
		pinMap.put("GPIO_10", RaspiPin.GPIO_10);
		pinMap.put("GPIO_11", RaspiPin.GPIO_11);
		pinMap.put("GPIO_12", RaspiPin.GPIO_12);
		pinMap.put("GPIO_13", RaspiPin.GPIO_13);
		pinMap.put("GPIO_14", RaspiPin.GPIO_14);
		pinMap.put("GPIO_15", RaspiPin.GPIO_15);
		pinMap.put("GPIO_16", RaspiPin.GPIO_16);
		pinMap.put("GPIO_17", RaspiPin.GPIO_17);
		pinMap.put("GPIO_18", RaspiPin.GPIO_18);
		pinMap.put("GPIO_19", RaspiPin.GPIO_19);
		pinMap.put("GPIO_20", RaspiPin.GPIO_20);
	}

	@Autowired
	private List<GpioListenerConfig> listenerConfigItems;

	public void initGpioListener() {
		for (GpioListenerConfig config : listenerConfigItems) {
			log.info("Add listener for {}", config);
			PinPullResistance resistance = config.isActionOnHigh() ? PinPullResistance.PULL_DOWN : PinPullResistance.PULL_UP;
			GpioPinDigitalInput pin = gpioController.provisionDigitalInputPin(getPin(config.getGpioPort()), resistance);
			pin.setShutdownOptions(true);
			pin.addListener(new GpioListener(config.getGpioAction(), config.isActionOnHigh(), config.getTimeout()));
		}
		log.info("Init finished");
	}

	private static Pin getPin(String pinDesc) {
		Pin pin = pinMap.get(pinDesc);
		if (pin == null) {
			throw new RuntimeException("Pin '" + pinDesc + "' is not defined.");
		}
		return pin;
	}
}
